package com.fecean.aabbc.netty.message7;

import lombok.extern.slf4j.Slf4j;

import java.time.Instant;
import java.util.Objects;
import java.util.UUID;

/**
 ** 消息建造器
 *
 * @author: chenfenghai
 * @version: 1.0
 * @date: 2020-03-10 14:31
 * @blame Team
 */
@Slf4j
public class MessageBuilder {

    /**
     ** Google Protocol Buffer数据对象
     */
    private GoogleProtobuf.DataObject dataObject;

    /**
     ** 消息对象
     */
    private AbstractMessage message;

    /**
     ** 构造注册消息
     *
     * @param tenantId 租户ID
     * @param cinemaCode 影院编码
     * @return RegisterMessage
     */
    public static RegisterMessage buildRegisterMessage(
            String tenantId, String cinemaCode){
        return RegisterMessage.builder()
                .id(UUID.randomUUID().toString())
                .tenantId(tenantId)
                .cinemaCode(cinemaCode)
                .timestamp(Instant.now().toEpochMilli())
                .build();
    }

    /**
     ** 构造心跳消息
     *
     * @param tenantId 租户ID
     * @param cinemaCode 影院编码
     * @return HeartbeatMessage
     */
    public static HeartbeatMessage buildHeartbeatMessage(
            String tenantId, String cinemaCode){
        return HeartbeatMessage.builder()
                .id(UUID.randomUUID().toString())
                .tenantId(tenantId)
                .cinemaCode(cinemaCode)
                .timestamp(Instant.now().toEpochMilli())
                .build();
    }

    /**
     ** 构造通知消息
     *
     * @param tenantId 租户ID
     * @param cinemaCode 影院编码
     * @param content 内容
     * @return NoticeMessage
     */
    public static NoticeMessage buildNoticeMessage(
            String tenantId, String cinemaCode, String content){
        return NoticeMessage.builder()
                .id(UUID.randomUUID().toString())
                .tenantId(tenantId)
                .cinemaCode(cinemaCode)
                .content(content)
                .timestamp(Instant.now().toEpochMilli())
                .build();
    }

    /**
     ** 构造请求消息
     *
     * @param tenantId 租户ID
     * @param cinemaCode 影院编码
     * @param content 内容
     * @return RequestMessage
     */
    public static RequestMessage buildRequestMessage(
            String tenantId, String cinemaCode, String content){
        return RequestMessage.builder()
                .id(UUID.randomUUID().toString())
                .tenantId(tenantId)
                .cinemaCode(cinemaCode)
                .content(content)
                .timestamp(Instant.now().toEpochMilli())
                .build();
    }

    /**
     ** 构造请求消息
     *
     * @param id 消息ID
     * @param tenantId 租户ID
     * @param cinemaCode 影院编码
     * @param content 内容
     * @return ResponseMessage
     */
    public static ResponseMessage buildResponseMessage(
            String id, String tenantId, String cinemaCode, String content){
        return ResponseMessage.builder()
                .id(id)
                .tenantId(tenantId)
                .cinemaCode(cinemaCode)
                .content(content)
                .timestamp(Instant.now().toEpochMilli())
                .build();
    }

    /**
     ** 建造消息
     *
     * @param object 消息内容
     * @return MessageBuilder
     */
    public static MessageBuilder of(Object object){
        Objects.requireNonNull(object, "消息不能为空");
        MessageBuilder builder = new MessageBuilder();
        if(object instanceof GoogleProtobuf.DataObject){
            builder.dataObject = (GoogleProtobuf.DataObject)object;
        }else {
            throw new IllegalArgumentException("参数[object]类型不正确");
        }
        return builder;
    }

    /**
     ** 转换为消息对象
     *
     * @return AbstractMessage
     */
    public AbstractMessage getMessage(){
        if(message != null){
            return message;
        }
        switch (MessageType.getEnum(dataObject.getType())){
            case REGISTER:
                message = RegisterMessage.builder()
                        .id(dataObject.getId())
                        .tenantId(dataObject.getTenantId())
                        .cinemaCode(dataObject.getCinemaCode())
                        .timestamp(dataObject.getTimestamp())
                        .build();
                break;
            case HEARTBEAT:
                message = HeartbeatMessage.builder()
                        .id(dataObject.getId())
                        .tenantId(dataObject.getTenantId())
                        .cinemaCode(dataObject.getCinemaCode())
                        .timestamp(dataObject.getTimestamp())
                        .build();
                break;
            case NOTICE:
                message = NoticeMessage.builder()
                        .id(dataObject.getId())
                        .tenantId(dataObject.getTenantId())
                        .cinemaCode(dataObject.getCinemaCode())
                        .content(dataObject.getContent())
                        .timestamp(dataObject.getTimestamp())
                        .build();
                break;
            case REQUEST:
                message = RequestMessage.builder()
                        .id(dataObject.getId())
                        .tenantId(dataObject.getTenantId())
                        .cinemaCode(dataObject.getCinemaCode())
                        .serviceName(dataObject.getServiceName())
                        .methodName(dataObject.getMethodName())
                        .content(dataObject.getContent())
                        .timestamp(dataObject.getTimestamp())
                        .build();
                break;
            case RESPONSE:
                message = ResponseMessage.builder()
                        .id(dataObject.getId())
                        .tenantId(dataObject.getTenantId())
                        .cinemaCode(dataObject.getCinemaCode())
                        .serviceName(dataObject.getServiceName())
                        .methodName(dataObject.getMethodName())
                        .content(dataObject.getContent())
                        .timestamp(dataObject.getTimestamp())
                        .build();
                break;
            default:
                throw new IllegalArgumentException("参数[object.type]不支持["+dataObject.getType()+"]类型");
        }
        return message;
    }


    /**
     ** 是否业务信息
     *
     * @param messageType 消息类型
     * @return boolean
     */
    public boolean isMessage(MessageType messageType){
        return dataObject != null && messageType.compare(dataObject.getType());
    }
}
